﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace Deferred.Library.Scene
{
    /// <summary>
    /// 
    /// </summary>
    public class SpotLight
    {
        /// <summary>
        /// 
        /// </summary>
        [ContentSerializer(Optional = true)]
        public Vector3 Position { get; set; }
        /// <summary>
        /// 
        /// </summary>
        [ContentSerializer(Optional = true)]
        public Color Color { get; set; }
        /// <summary>
        /// 
        /// </summary>
        [ContentSerializer(Optional = true)]
        public float Radius { get; set; }
        /// <summary>
        /// 
        /// </summary>
        [ContentSerializer(Optional = true)]
        public float Angle { get; set; }
        /// <summary>
        /// 
        /// </summary>
        [ContentSerializer(Optional = true)]
        public float DecayExponent { get; set; }
        /// <summary>
        /// 
        /// </summary>
        [ContentSerializer(Optional = true)]
        public Vector3 LookAt { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [ContentSerializerIgnore]
        public float AngleCosine { get { return (float)Math.Cos(Angle / 2); } }
        /// <summary>
        /// 
        /// </summary>
        [ContentSerializerIgnore]
        public Vector3 NormalLookAt { get { return Vector3.Normalize(LookAt); } }
        /// <summary>
        /// 
        /// </summary>
        [ContentSerializerIgnore]
        public Matrix World
        {
            get
            {
                Vector3 lookAtNorm = Vector3.Normalize(LookAt);
                Vector3 axis;
                float angle;

                if (Vector3.Up.Equals(lookAtNorm))
                {
                    axis = Vector3.Right;
                    angle = (float)Math.PI;
                }
                else
                {
                    axis = Vector3.Cross(Vector3.Down, lookAtNorm);
                    angle = (float)Math.Acos(Vector3.Dot(Vector3.Down, lookAtNorm));
                }
                float xzScale = (float)(Math.Tan(Angle / 2) * Radius);

                return Matrix.CreateScale(xzScale, Radius, xzScale) * Matrix.CreateFromAxisAngle(axis, angle) * Matrix.CreateTranslation(Position);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public SpotLight()
            : this(new Vector3(), new Color(), 1, MathHelper.Pi / 2, 0, Vector3.Down) { }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="position"></param>
        /// <param name="color"></param>
        /// <param name="radius"></param>
        /// <param name="angle"></param>
        /// <param name="decayExponent"></param>
        /// <param name="lookAt"></param>
        public SpotLight(Vector3 position, Color color, float radius, float angle, float decayExponent, Vector3 lookAt)
        {
            this.Position = position;
            this.Color = color;
            this.Radius = radius;
            this.Angle = angle;
            this.DecayExponent = decayExponent;
            this.LookAt = lookAt;
        }
    }
}
